home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Programmer Power Tools
/
Programmer Power Tools.iso
/
screen
/
herc_eps.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1988-01-19
|
8KB
|
208 lines
Date: Wed, 6 Jan 88 12:59 EST
From: P150BK19@VB.CC.CMU.EDU
Subject: Hercules-to-Epson Turbo Pascal code
To: hicks@WALKER-EMH.ARPA
Procedure HGCopy;
(* This procedure produces a hard copy of a Hercules screen on an
Epson-compatible printer (mode 1) using inline code, which is considerably
faster than the HardCopy procedure provided with the Turbo Graphix ToolBox.
On a Panasonic XK-P1080i, which can print 8-bit double-density graphics (mode
1) at 6 inches per second, this routine essentially keeps the printer fully
occupied. About half of the speedup over the ToolBox version comes from
using inline code to map the graphics bits to a print row, and the other half
comes from using inline code to print the row itself (instead of a "write"
call for each and every byte of dots). While the procedure uses variables
which are defined from the Graphix ToolBox, owning the ToolBox is not
strictly necessary (of course you must then supply your own drivers). The
key variables are:
GrafBase : segment address of active screen
(hardware screen is $B000);
XScreenMaxGlb : width of screen (in pixels) - 1;
XMaxGlb : (XScreenMaxGlb - 7) / 8; width of screen in bytes - 1;
The screen is mapped to a print row which is 8 bits high, corresponding to 8
scan lines. The Hercules scan lines are stored in 4 sectors, the low address
of which are separated by $2000. Each print row thus contains two successive
scan lines from each sector. It is also assumed that the screen has 352 scan
lines (as is used in the ToolBox, in spite of the Hercules specification of
348), corresponding to exactly 44 8-bit print rows. This can also be changed
directly in the main portion of the procedure. *)
type
LineType = array [0..XScreenMaxGlb] of Byte;
var
PrintLine : LineType;
PrntChrPtr,LinePtr,SectorPtr,ScanPtr,
PrtLineNum, ByteNum : integer;
WorkByte : Byte;
Procedure MapLine(LinePtr, XMaxLoc, XScreenMaxLoc : integer;
var PrintLine : LineType);
{inline procedure to map a single print line }
var
ScanBitLoc : integer;
begin {MapLine}
XMaxLoc := XMaxGlb; {get Local variable versions for inline code}
XScreenMaxLoc := XScreenMaxGlb; {which utilizes stack segment}
Inline(
$C4/$9E/>PrintLine/ { LES BX,>PrintLine[BP] }
{ set print line to zero }
$89/$D9/ { MOV CX,BX }
$03/$8E/>XScreenMaxLoc/ { ADD CX,>XScreenMaxLoc[BP] }
$31/$C0/ { XOR AX,AX }
{ ZeroStringLoop: }
$26/ { ES: ; PrintLine in extra segment! }
$88/$07/ { MOV [BX],AL }
$43/ { INC BX }
$39/$CB/ { CMP BX,CX }
$7E/$F8/ { JLE ZeroStringLoop }
{ SectorPtr := LinePtr }
$8B/$BE/>LinePtr/ { MOV DI,>LinePtr[BP] ; SectorPtr }
{ for SectorBitLoc := 7 downto 4 do }
{ 4 Sectors in memory }
$B9/$07/$00/ { MOV CX,7 }
{ SectorLoop: }
{ ScanBitLoc := SectorBitLoc }
$89/$8E/>ScanBitLoc/ { MOV >ScanBitLoc[BP],CX }
{ ScanPtr := SectorPtr }
$57/ { PUSH DI }
$51/ { PUSH CX }
$31/$C9/ { XOR CX,CX }
{ for ScanNum := 0 to 1 do }
{ 2 Scan Lines per Sector }
{ ScanLineLoop: }
$C4/$9E/>PrintLine/ { LES BX,>PrintLine[BP] ; PrntChrPtr }
$51/ { PUSH CX }
$31/$C9/ { XOR CX,CX }
{ for ByteNum := 0 to XMaxLoc do }
{ 90 Bytes/Scan Line }
{ ByteScanLoop: }
{ WorkByte := mem[GrafBase:ScanPtr] }
$06/ { PUSH ES }
$A1/>GrafBase/ { MOV AX,[>GrafBase] }
$8E/$C0/ { MOV ES,AX }
$26/ { ES: }
$8A/$05/ { MOV AL,[DI] }
$07/ { POP ES }
$51/ { PUSH CX }
$BA/$07/$00/ { MOV DX,7 }
{ for BitNum := 7 downto 0 do }
{ Scan single Byte }
{ BitScanLoop: }
{ mem[PrntSeg:PrntChrPtr]
:= mem[PrntSeg:PrntChrPtr] or
( ( (WorkByte shr BitNum) and 1 ) shl ScanBitLoc ) }
$88/$C4/ { MOV AH,AL }
$89/$D1/ { MOV CX,DX }
$D2/$EC/ { SHR AH,CL }
$80/$E4/$01/ { AND AH,1 }
$8B/$8E/>ScanBitLoc/ { MOV CX,>ScanBitLoc[BP] }
$D2/$E4/ { SHL AH,CL }
$26/ { ES: }
{ PrintLine in extra segment }
$08/$27/ { OR [BX],AH }
{ PrntChrPtr := PrntChrPtr + 1 }
$43/ { INC BX }
$4A/ { DEC DX }
$81/$FA/$00/$00/ { CMP DX,0 }
$7D/$E6/ { JGE BitScanLoop }
$59/ { POP CX }
{ ScanPtr := ScanPtr + 1 }
$47/ { INC DI }
$41/ { INC CX }
$3B/$8E/>XMaxLoc/ { CMP CX,>XMaxLoc[BP] }
$7E/$CF/ { JLE ByteScanLoop }
$59/ { POP CX }
{ ScanBitLoc := ScanBitLoc - 4 }
$8B/$9E/>ScanBitLoc/ { MOV BX,>ScanBitLoc[BP] }
$81/$EB/$04/$00/ { SUB BX,4 }
$89/$9E/>ScanBitLoc/ { MOV >ScanBitLoc[BP],BX }
$41/ { INC CX }
$81/$F9/$01/$00/ { CMP CX,1 }
$7E/$B4/ { JLE ScanLineLoop }
$59/ { POP CX }
{ SectorPtr := SectorPtr + $2000 }
$5F/ { POP DI }
$81/$C7/$00/$20/ { ADD DI,$2000 }
$49/ { DEC CX }
$81/$F9/$04/$00/ { CMP CX,4 }
$7D/$9F); { JGE SectorLoop }
end; {MapLine}
Procedure PrintByte (OneByte : Byte);
begin {PrintByte}
Inline(
$31/$D2/ { XOR DX,DX }
$B4/$00/ { MOV AH,0 }
$8A/$86/>OneByte/ { MOV AL,>OneByte[BP] }
$CD/$17); { INT $17 }
end; {PrintByte}
Procedure PrintRow (XScreenMaxLoc : integer; var PrintLine : LineType);
begin {PrintRow}
Inline(
$C4/$9E/>PrintLine/ { LES BX,>PrintLine[BP] }
$89/$D9/ { MOV CX,BX }
$03/$8E/>XscreenMaxLoc/ { ADD CX,>XScreenMaxLoc[BP] }
{ for ByteNum := 0 to XScreenMaxGlb do }
{PrintLoop: }
{ Write(Lst, Chr( PrintLine[ByteNum]) ) }
$31/$D2/ { XOR DX,DX }
$B4/$00/ { MOV AH,0 }
$26/ { ES: }
$8A/$07/ { MOV AL,[BX] }
$CD/$17/ { INT $17 }
$43/ { INC BX }
$39/$CB/ { CMP BX,CX }
$7E/$F2); { JLE PrintLoop }
end; {PrintRow}
begin { HGCopy }
PrintByte(27); {set Line spacing to 9/inch}
PrintByte(Byte('3'));
PrintByte(24);
LinePtr := 0; {start with 0 offset from GrafBase}
for PrtLineNum := 1 to 44 do {44 total print Lines}
begin
MapLine(LinePtr, XMaxGlb, XScreenMaxGlb, PrintLine);
{map the Bits with an inLine procedure}
{now print the Line}
PrintByte(27); {force EPSON mode 1 for now}
PrintByte(Byte('L'));
PrintByte(Lo(XScreenMaxGlb + 1));
PrintByte(Hi(XScreenMaxGlb + 1));
PrintRow(XScreenMaxGlb, PrintLine); {print row of Bytes}
PrintByte(10);
LinePtr := LinePtr + 2 * (XMaxGlb + 1); {jump 2 scan lines / print row}
end; {print Line Loop}
PrintByte(27); {reset printer}
PrintByte(Byte('2'));
end; {HGCopy}